﻿using MvvmFoundation.Wpf;
using ServiceOperater.Behaviors;
using ServiceOperater.Helpers;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace ServiceOperater.ViewModels
{
    public sealed class AnalysisResultViewModel : ObservableObject
    {

        public AnalysisResultViewModel()
        {
            this.ServiceFileCollection = new ObservableCollection<FileTreeNodeViewModel>();
            this.MybatisNodeVmCollection = new ObservableCollection<MyBatisNodeViewModel>();

            instantiateCommand();
        }


        private void instantiateCommand()
        {
            AnalysisCommand = new RelayCommand<Object>((obj) =>
            {
                IsAnalysisServiceBusy = true;
                IsAnalysisMybatisBusy = true;

                background_analysisService();
                //background_analysisMybatis();
                //
            }, (obj) =>
            {
                return true;
            });

            OnServiceComboboxSelectedChangedCommand = new RelayCommand<int>((selectedIndex) =>
            {
                switch (selectedIndex)
                {
                    case 0:
                        showAllService(this.ServiceFileCollection);
                        break;
                    case 1:
                        onlyShowUsedService(this.ServiceFileCollection);
                        break;
                    case 2:
                        onlyShowUnUsedService(this.ServiceFileCollection);
                        break;
                    default:
                        break;
                }

            }, (obj) =>
            {
                return this.ServiceFileCollection.Count > 0;
            });

            OnlySeeUnUsedMybatisCommand = new RelayCommand<Object>((obj) =>
            {

            }, (obj) =>
            {
                return true;
            });
        }

        private void showAllService(ObservableCollection<FileTreeNodeViewModel> serviceFileCollection)
        {
            foreach (var serviceFileVm in serviceFileCollection)
            {
                if (serviceFileVm.IsDirectory)
                {
                    showAllService(serviceFileVm.Children);
                }
                else
                {
                    serviceFileVm.IsVisible = true;
                    serviceFileVm.IsExpanded = true;
                    serviceFileVm.IsSelected = false;
                    foreach (var serviceVm in serviceFileVm.ServiceCollection)
                    {
                        serviceVm.IsVisible = true;
                    }
                }
            }
        }

        private void onlyShowUsedService(ObservableCollection<FileTreeNodeViewModel> serviceFileCollection)
        {
            foreach (var serviceFileVm in serviceFileCollection)
            {
                if (serviceFileVm.IsDirectory)
                {
                    onlyShowUsedService(serviceFileVm.Children);
                }
                else
                {
                    serviceFileVm.IsExpanded = true;
                    serviceFileVm.IsSelected = false;
                    foreach (var serviceVm in serviceFileVm.ServiceCollection)
                    {
                        if (serviceVm.FoundFileInfoList.Count != 0)
                        {
                            serviceVm.IsVisible = true;
                            // 如果包含该service的文件tree node不可见, 则将该文件tree node显示
                            if (!serviceVm.LocationFile.IsVisible)
                            {
                                serviceVm.LocationFile.IsVisible = true;
                            }
                        }
                        else
                        {
                            serviceVm.IsVisible = false;
                            // 如果包含该service的文件tree node旗下的service都不可见, 则将其也隐藏
                            if (serviceVm.LocationFile.ServiceCollection.All(s => !s.IsVisible))
                            {
                                serviceVm.LocationFile.IsVisible = false;
                            }
                        }
                    }
                }
            }
        }

        private void onlyShowUnUsedService(ObservableCollection<FileTreeNodeViewModel> serviceFileCollection)
        {
            foreach (var serviceFileVm in serviceFileCollection)
            {
                if (serviceFileVm.IsDirectory)
                {
                    onlyShowUnUsedService(serviceFileVm.Children);
                }
                else
                {
                    serviceFileVm.IsExpanded = true;
                    serviceFileVm.IsSelected = false;
                    foreach (var serviceVm in serviceFileVm.ServiceCollection)
                    {
                        if (serviceVm.FoundFileInfoList.Count == 0)
                        {
                            serviceVm.IsVisible = true;
                            // 如果包含该service的文件tree node不可见, 则将该文件tree node显示
                            if (!serviceVm.LocationFile.IsVisible)
                            {
                                serviceVm.LocationFile.IsVisible = true;
                            }
                        }
                        else
                        {
                            serviceVm.IsVisible = false;
                            // 如果包含该service的文件tree node旗下的service都不可见, 则将其也隐藏
                            if (serviceVm.LocationFile.ServiceCollection.All(s => !s.IsVisible))
                            {
                                serviceVm.LocationFile.IsVisible = false;
                            }
                        }
                    }
                }
            }
        }

        private void background_analysisService()
        {
            // 《Pro WPF 4.5 in C# (4th Edition)》Chapter31 P991
            System.ComponentModel.BackgroundWorker backgroundWorker = new System.ComponentModel.BackgroundWorker();
            //-------------------------------- event handler
            backgroundWorker.DoWork += (sender, args) =>
            {
                ObservableCollection<FileTreeNodeViewModel> fileCollection = new ObservableCollection<FileTreeNodeViewModel>();
                string dirPath = ConfigHelper.ServiceFolderPath;//文件夹起始的路径
                var directory = new DirectoryInfo(dirPath);
                MainViewModel.constructTree(directory, fileCollection);

                analysisService(fileCollection);

                args.Result = fileCollection;

            };
            backgroundWorker.ProgressChanged += (sender, args) =>
            {
                // object sender, System.ComponentModel.ProgressChangedEventArgs e
            };
            backgroundWorker.RunWorkerCompleted += (sender, args) =>
            {
                // object sender, System.ComponentModel.RunWorkerCompletedEventArgs e
                this.ServiceFileCollection.Clear();

                var fileCollection = (ObservableCollection<FileTreeNodeViewModel>)args.Result;
                foreach (var fileVm in fileCollection)
                {
                    this.ServiceFileCollection.Add(fileVm);
                }

                IsAnalysisServiceBusy = false;
            };

            backgroundWorker.RunWorkerAsync();

        }

        private void analysisService(ObservableCollection<FileTreeNodeViewModel> serviceFileCollection)
        {
            foreach (var fileVm in serviceFileCollection)
            {
                MainViewModel.loadServiceXmlFile(fileVm);

                // 接下来每个FileTreeNodeViewModel里的serviceVm, 以及serviceVm中的Action都是最新的
                foreach (var serviceVm in fileVm.ServiceCollection)
                {
                    //筛选JS文件中包含该service的
                    List<FoundFileInfo> locationList = FileFinder.Find(ConfigHelper.FrontFolderPath, "*.js", serviceVm.Id);
                    serviceVm.FoundFileInfoList.Clear();
                    foreach (var item in locationList)
                    {
                        serviceVm.FoundFileInfoList.Add(item);
                    }

                    // java文件中包含该service
                    locationList = FileFinder.Find(ConfigHelper.JavaFolderPath, "*.java", serviceVm.Id);
                    foreach (var item in locationList)
                    {
                        serviceVm.FoundFileInfoList.Add(item);
                    }

                    // 还是一个都没找到
                    if (serviceVm.FoundFileInfoList.Count == 0)
                    {
                        //TODO 警告了; 旗下所有的action对应的mybatis要作废
                    }
                }
            }
        }

        private void background_analysisMybatis()
        {
            // 《Pro WPF 4.5 in C# (4th Edition)》Chapter31 P991
            System.ComponentModel.BackgroundWorker backgroundWorker = new System.ComponentModel.BackgroundWorker();
            //-------------------------------- event handler
            backgroundWorker.DoWork += (sender, args) =>
            {
                var mybatisNodeVmList = analysisMybatis();

                //mybatisNodeVmList.GroupBy(mybatisNodeVm =>
                //{
                //    return mybatisNodeVm.Namespace;
                //});

                args.Result = mybatisNodeVmList;

            };
            backgroundWorker.RunWorkerCompleted += (sender, args) =>
            {
                foreach (var item in (List<MyBatisNodeViewModel>)args.Result)
                {
                    this.MybatisNodeVmCollection.Add(item);
                }
                this.IsAnalysisMybatisBusy = false;
            };

            backgroundWorker.RunWorkerAsync();
        }

        private List<MyBatisNodeViewModel> analysisMybatis()
        {
            //------以上分析出没有被使用的service
            // 我们还需要分析出没有被使用的mybatis
            List<MyBatisNodeViewModel> mybatisNodeVmList = new List<MyBatisNodeViewModel>();
            loadMybatisXmlFile(ConfigHelper.MybatisFolderPath, mybatisNodeVmList);
            foreach (var mybatisNodeVm in mybatisNodeVmList)
            {
                // 出现在java中的
                List<FoundFileInfo> locationListInJava = FileFinder.Find(ConfigHelper.JavaFolderPath, "*.java", mybatisNodeVm.Id);
                // 出现在service中的
                List<FoundFileInfo> locationListInService = FileFinder.Find(ConfigHelper.ServiceFolderPath, "*.xml", mybatisNodeVm.Id);

                foreach (var item in locationListInJava)
                {
                    mybatisNodeVm.FoundFileInfoList.Add(item);
                }

                foreach (var item in locationListInService)
                {
                    mybatisNodeVm.FoundFileInfoList.Add(item);
                }
            }

            return mybatisNodeVmList;
        }


        private void loadMybatisXmlFile(String filePath, List<MyBatisNodeViewModel> mybatisNodeVmList)
        {
            if (FileHelper.isDir(filePath))
            {
                var di = new DirectoryInfo(filePath);
                FileInfo[] fileInfoColleciton = di.GetFiles("*.xml");//指定类型
                foreach (FileInfo fileInfo in fileInfoColleciton)
                {
                    mybatisNodeVmList.AddRange(collectMybatisNode(fileInfo));
                }

                DirectoryInfo[] dirInfoColleciton = di.GetDirectories();
                foreach (DirectoryInfo dirInfo in dirInfoColleciton)
                {
                    loadMybatisXmlFile(dirInfo.FullName, mybatisNodeVmList);
                }
            }
            else
            {
                mybatisNodeVmList.AddRange(collectMybatisNode(new FileInfo(filePath)));
            }
        }

        private List<MyBatisNodeViewModel> collectMybatisNode(FileInfo fileInfo)
        {
            // http://www.cnblogs.com/hnsongbiao/p/5636076.html
            XmlDocument doc = new XmlDocument();
            doc.Load(fileInfo.FullName);
            XmlElement root = doc.DocumentElement;

            var rootMapper = root.SelectSingleNode("/mapper");
            var namespaceStr = rootMapper.Attributes["namespace"].InnerText;


            List<MyBatisNodeViewModel> lst = new List<MyBatisNodeViewModel>();
            XmlNodeList actionNodeList = root.SelectNodes("select|insert|update|delete");
            foreach (XmlNode actionNode in actionNodeList)
            {
                var actionId = actionNode.Attributes["id"].InnerText;
                var mybatisNodeVm = new MyBatisNodeViewModel(fileInfo.FullName, namespaceStr)
                {
                    Id = actionId
                };

                lst.Add(mybatisNodeVm);
            }

            return lst;
        }

        #region Props
        public ObservableCollection<FileTreeNodeViewModel> ServiceFileCollection { get; private set; }
        public ObservableCollection<MyBatisNodeViewModel> MybatisNodeVmCollection { get; private set; }

        private string text = "忙,请等待！";
        public string Text
        {
            get
            {
                return text;
            }
            set
            {
                if (text == value)
                {
                    return;
                }

                text = value;
                RaisePropertyChanged("Text");
            }
        }

        private bool isAnalysisServiceBusy = false;
        public bool IsAnalysisServiceBusy
        {
            get
            {
                return isAnalysisServiceBusy;
            }
            set
            {
                if (isAnalysisServiceBusy == value)
                {
                    return;
                }

                isAnalysisServiceBusy = value;

                RaisePropertyChanged("IsAnalysisServiceBusy");
            }
        }

        private bool isAnalysisMybatisBusy = false;
        public bool IsAnalysisMybatisBusy
        {
            get
            {
                return isAnalysisMybatisBusy;
            }
            set
            {
                if (isAnalysisMybatisBusy == value)
                {
                    return;
                }

                isAnalysisMybatisBusy = value;

                RaisePropertyChanged("IsAnalysisMybatisBusy");
            }
        }

        #endregion

        #region Commands

        public RelayCommand<Object> AnalysisCommand { get; private set; }
        public RelayCommand<int> OnServiceComboboxSelectedChangedCommand { get; private set; }
        public RelayCommand<Object> OnlySeeUnUsedMybatisCommand { get; private set; }

        #endregion


    }





}
